﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;

namespace SocketServer {
  /// <summary>
  /// MainWindow.xaml 的交互逻辑
  /// </summary>
  public partial class MainWindow: Window {
    public MainWindow() {
      InitializeComponent();

      //Action action =new Action(Listen)
    }

    private Socket _send;
    private readonly Dictionary<EndPoint, Socket> _remoteClientLists = new Dictionary<EndPoint, Socket>();
    private void StartListen_OnClick(object sender, RoutedEventArgs e) {
      // 创建一个负责监听的socket
      Socket watch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      // 创建监听的IP地址，
      // Any表示提供一个 IP 地址，指示服务器应侦听所有网络接口上的客户端活动。此字段为只读。
      IPAddress ip = IPAddress.Any;
      // 创建端口号
      IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(Port.Text));
      // 监听
      watch.Bind(point);
      ShowMsg("开始监听");
      // 设置监听队列
      watch.Listen(10);
      // 开启新线程
      Thread th = new Thread(Listen) { IsBackground = true };
      th.Start(watch);



    }
    /// <summary>
    /// 等待客户端的连接，并创建与之通信的socket
    /// </summary>
    /// <param name="o"></param>
    private void Listen(object o) {
      var watch = o as Socket;
      while (true) {
        try {
          // 等待客户端连接，并创建一个负责通信的socket
          _send = watch?.Accept();
          ShowMsg($"{_send?.RemoteEndPoint}:监听成功");

          // 将客户端存入下拉列表和字典中
          _remoteClientLists.Add(_send.RemoteEndPoint, _send);
          RemoteClientList.Dispatcher.Invoke(() => {
            RemoteClientList.Items.Add(_send.RemoteEndPoint.ToString());
          });

          // 开启新线程
          Thread th = new Thread(ReceiveData) { IsBackground = true };
          th.Start(_send);
        } catch {
          // 
        }
      }
    }

    /// <summary>
    /// 接收客户端发送的数据
    /// </summary>
    private void ReceiveData(object obj) {
      Socket send = obj as Socket;
      while (true) {
        try {
          // 客户端连接成功后，服务器接受客户端发来的信息
          byte[] buffer = new byte[1024 * 1024 * 5]; // 5MB

          int count = send.Receive(buffer);
          if (count == 0) return;
          // 解码
          string str = Encoding.UTF8.GetString(buffer, 0, count);
          ShowMsg($"{send.RemoteEndPoint}: {str}");
        } catch {
          // 不做处理
        }
      }
    }

    private delegate void ShowMessage(string info);
    private void ShowMsg(string info) {
      // 消除跨线程访问的错误
      this.ShowListenInformation.Dispatcher.Invoke(new ShowMessage(Msg), info);
    }
    private void Msg(string info) {
      ShowListenInformation.AppendText($"{info} \r\n");
    }

    // 向客户端发送消息
    private void SendMessage_OnClick(object sender, RoutedEventArgs e) {
      IPEndPoint ipEndPoint;
      byte[] datas = Encoding.UTF8.GetBytes(SendedMessageBox.Text.Trim());
      List<byte> list = new List<byte>();
      list.Add(0);
      list.AddRange(datas);

      try {

        string ipAndPortStr = RemoteClientList.Text;
        string[] ipAndPort = ipAndPortStr.Split(new[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
        string ip = ipAndPort[0];
        string port = ipAndPort[1];
        IPAddress ipAddr = IPAddress.Parse(ip);
        ipEndPoint = new IPEndPoint(ipAddr, Convert.ToInt32(port));
      } catch {
        MessageBox.Show("发送失败");
        return;
      }
      _remoteClientLists[ipEndPoint].Send(list.ToArray());
      SendedMessageBox.Text = "";
    }
  }
}
